#include "app_securityaccess.h"
#include "UDS_SeedKey.h"
#include "app_upgrade.h"
#if 0
const unsigned char level1_key[16] = {
	0x3d, 0x2e, 0x6d, 0xe2, 0xa1, 0x25, 0x17, 0xba,
	0xc5, 0xb3, 0x1b, 0xbd, 0x0e, 0x7e, 0x3b, 0x54
};
const unsigned char level3_key[16] = {
	0xD0, 0xDF, 0xAA, 0x15, 0x88, 0xE0, 0x4B, 0x5B,
	0x14, 0xCE, 0x83, 0x4E, 0x65, 0xE6, 0x21, 0xCD
};
#else
const unsigned char level1_key[16] = {
	0x22, 0x52, 0xEB, 0x87, 0x52, 0x26, 0xFB, 0x33, 
	0xBD, 0x2A, 0x85, 0x73, 0x5E, 0xA1, 0x7A, 0xFA
};
const unsigned char level3_key[16] = {
	0x9E, 0x38, 0x3E, 0x45, 0x4F, 0x6A, 0x67, 0x8D, 
	0xA6, 0xA6, 0x4F, 0x45, 0x73, 0xD6, 0x68, 0x18
};
#endif

extern void AES_CMAC(unsigned char *key, unsigned char *input, int length,
	unsigned char *mac);



// security access
Std_ReturnType Diag_GetSeed_Unlock (uint8 *securityAccessDataRecord, uint8 *seed, Dcm_NegativeResponseCodeType *errorCode)
{
	*seed = 0;
	*errorCode = DCM_E_POSITIVERESPONSE;
	return E_OK;
}
Std_ReturnType Diag_CompareSeed_Unlock (uint8 *key)
{
	*key = 0;
	return E_OK;
}

uint32 u32sysTickCounter=0;
static uint8_t calcSeed1[16] = {0},calcSeed2[16] = {0};
extern uint32_t mid_systimer_getcount(void);
static void securityAccessGenerateSeed(uint8 seed[],uint8 length, uint32 lseed)
{
	uint8 lcvtemp;

	srand(lseed);
	
	for(lcvtemp=0;lcvtemp<length;lcvtemp++)
	{
		seed[lcvtemp]=(rand()%255) ;	
	}
}

Std_ReturnType Security_GetSeed_Level0 (uint8 *securityAccessDataRecord, uint8 *seed, Dcm_NegativeResponseCodeType *errorCode)
{
	return E_OK;
}

Std_ReturnType Security_CompKey_Level0 (uint8 *key)
{
	return E_OK;
}

Std_ReturnType Security_CompKey_Level (uint8_t level, uint8_t *key)
{
	unsigned long security_access_key  =0;
	unsigned long in_key  =0;
    unsigned char mac[16]={0};
	uint8_t SecM_Status = SECM_OK;
		
	switch (level)
    {
    	case 1:
            AES_CMAC((unsigned char*)level1_key, calcSeed1, 16, mac);
    		break;
    	case 3:
            AES_CMAC((unsigned char*)level3_key, calcSeed1, 16, mac);
    		break;
    	default:
    		break;
    }	
	SecM_Status = memcmp(key,mac,16);
	if(SecM_Status == SECM_OK)   
    {
        return E_OK;
    }
    else
    {
        return E_NOT_OK;
    }
}
Std_ReturnType Security_GetSeed_Level1 (uint8 *securityAccessDataRecord, uint8 *seed, Dcm_NegativeResponseCodeType *errorCode)
{
	uint8 lcvtemp;
	uint32 g_sys_tick = 0;
	g_sys_tick = mid_systimer_getcount();
	(void)securityAccessDataRecord;
	
	for(lcvtemp=0;lcvtemp<100;lcvtemp++)
	{
		securityAccessGenerateSeed(calcSeed1,16,g_sys_tick);
		if( ( calcSeed1[0]+calcSeed1[1]+calcSeed1[2]+calcSeed1[3]+
              calcSeed1[4]+calcSeed1[5]+calcSeed1[6]+calcSeed1[7]+
              calcSeed1[8]+calcSeed1[9]+calcSeed1[10]+calcSeed1[11]+
              calcSeed1[12]+calcSeed1[13]+calcSeed1[14]+calcSeed1[15] )%100!=0 )
		{
			break;
		}
	}
	
	if( ( calcSeed1[0]+calcSeed1[1]+calcSeed1[2]+calcSeed1[3]+
              calcSeed1[4]+calcSeed1[5]+calcSeed1[6]+calcSeed1[7]+
              calcSeed1[8]+calcSeed1[9]+calcSeed1[10]+calcSeed1[11]+
              calcSeed1[12]+calcSeed1[13]+calcSeed1[14]+calcSeed1[15] )%100!=0 )
	{
		for(lcvtemp=0;lcvtemp<( ( calcSeed1[0]+calcSeed1[1]+calcSeed1[2]+calcSeed1[3]+
                                  calcSeed1[4]+calcSeed1[5]+calcSeed1[6]+calcSeed1[7]+
                                  calcSeed1[8]+calcSeed1[9]+calcSeed1[10]+calcSeed1[11]+
                                  calcSeed1[12]+calcSeed1[13]+calcSeed1[14]+calcSeed1[15] )%100);lcvtemp++)
		{
			securityAccessGenerateSeed(calcSeed2,16,(g_sys_tick+lcvtemp));	
		}
	}
	else
	{
		securityAccessGenerateSeed(calcSeed2,16,g_sys_tick);	
	}
	*seed++ = calcSeed2[15];
	*seed++ = calcSeed2[14];
	*seed++ = calcSeed2[13];
	*seed++ = calcSeed2[12];
    *seed++ = calcSeed2[11];
	*seed++ = calcSeed2[10];
	*seed++ = calcSeed2[9];
	*seed++ = calcSeed2[8];
    *seed++ = calcSeed2[7];
	*seed++ = calcSeed2[6];
	*seed++ = calcSeed2[5];
	*seed++ = calcSeed2[4];
    *seed++ = calcSeed2[3];
	*seed++ = calcSeed2[2];
	*seed++ = calcSeed2[1];
	*seed++ = calcSeed2[0];
	
	calcSeed1[15] = calcSeed2[0];
	calcSeed1[14] = calcSeed2[1];
	calcSeed1[13] = calcSeed2[2];
	calcSeed1[12] = calcSeed2[3];
    calcSeed1[11] = calcSeed2[4];
	calcSeed1[10] = calcSeed2[5];
	calcSeed1[9] = calcSeed2[6];
	calcSeed1[8] = calcSeed2[7];
    calcSeed1[7] = calcSeed2[8];
	calcSeed1[6] = calcSeed2[9];
	calcSeed1[5] = calcSeed2[10];
	calcSeed1[4] = calcSeed2[11];
    calcSeed1[3] = calcSeed2[12];
	calcSeed1[2] = calcSeed2[13];
	calcSeed1[1] = calcSeed2[14];
	calcSeed1[0]= calcSeed2[15];

    *errorCode = E_OK;
    return E_OK;
}
Std_ReturnType Security_CompKey_Level1 (uint8 *key)
{
	return Security_CompKey_Level(1, key);
}
Std_ReturnType Security_GetSeed_Level3 (uint8 *securityAccessDataRecord, uint8 *seed, Dcm_NegativeResponseCodeType *errorCode)
{
	uint8 lcvtemp;
	uint32 g_sys_tick = 0;
	g_sys_tick = mid_systimer_getcount();
	(void)securityAccessDataRecord;
	
	for(lcvtemp=0;lcvtemp<100;lcvtemp++)
	{
		securityAccessGenerateSeed(calcSeed1,16,g_sys_tick);
		if( ( calcSeed1[0]+calcSeed1[1]+calcSeed1[2]+calcSeed1[3]+
              calcSeed1[4]+calcSeed1[5]+calcSeed1[6]+calcSeed1[7]+
              calcSeed1[8]+calcSeed1[9]+calcSeed1[10]+calcSeed1[11]+
              calcSeed1[12]+calcSeed1[13]+calcSeed1[14]+calcSeed1[15] )%100!=0 )
		{
			break;
		}
	}
	
	if( ( calcSeed1[0]+calcSeed1[1]+calcSeed1[2]+calcSeed1[3]+
          calcSeed1[4]+calcSeed1[5]+calcSeed1[6]+calcSeed1[7]+
          calcSeed1[8]+calcSeed1[9]+calcSeed1[10]+calcSeed1[11]+
          calcSeed1[12]+calcSeed1[13]+calcSeed1[14]+calcSeed1[15] )%100!=0 )
	{
		for(lcvtemp=0;lcvtemp<( ( calcSeed1[0]+calcSeed1[1]+calcSeed1[2]+calcSeed1[3]+
                                  calcSeed1[4]+calcSeed1[5]+calcSeed1[6]+calcSeed1[7]+
                                  calcSeed1[8]+calcSeed1[9]+calcSeed1[10]+calcSeed1[11]+
                                  calcSeed1[12]+calcSeed1[13]+calcSeed1[14]+calcSeed1[15] )%100);lcvtemp++)
		{
			securityAccessGenerateSeed(calcSeed2,16,(g_sys_tick+lcvtemp));	
		}
	}
	else
	{
		securityAccessGenerateSeed(calcSeed2,16,g_sys_tick);	
	}
	*seed++ = calcSeed2[15];
	*seed++ = calcSeed2[14];
	*seed++ = calcSeed2[13];
	*seed++ = calcSeed2[12];
    *seed++ = calcSeed2[11];
	*seed++ = calcSeed2[10];
	*seed++ = calcSeed2[9];
	*seed++ = calcSeed2[8];
    *seed++ = calcSeed2[7];
	*seed++ = calcSeed2[6];
	*seed++ = calcSeed2[5];
	*seed++ = calcSeed2[4];
    *seed++ = calcSeed2[3];
	*seed++ = calcSeed2[2];
	*seed++ = calcSeed2[1];
	*seed++ = calcSeed2[0];
	
	calcSeed1[15] = calcSeed2[0];
	calcSeed1[14] = calcSeed2[1];
	calcSeed1[13] = calcSeed2[2];
	calcSeed1[12] = calcSeed2[3];
    calcSeed1[11] = calcSeed2[4];
	calcSeed1[10] = calcSeed2[5];
	calcSeed1[9] = calcSeed2[6];
	calcSeed1[8] = calcSeed2[7];
    calcSeed1[7] = calcSeed2[8];
	calcSeed1[6] = calcSeed2[9];
	calcSeed1[5] = calcSeed2[10];
	calcSeed1[4] = calcSeed2[11];
    calcSeed1[3] = calcSeed2[12];
	calcSeed1[2] = calcSeed2[13];
	calcSeed1[1] = calcSeed2[14];
	calcSeed1[0]= calcSeed2[15];

    *errorCode = E_OK;
    return E_OK;
}
Std_ReturnType Security_CompKey_Level3(uint8 *key)
{
	return Security_CompKey_Level(3, key);
}


